package com.upcontrol.uartagent.core;

import android.content.Context;

import com.csjbot.csjbase.log.Csjlogger;
import com.upcontrol.uartagent.core.inter.DataReceive;
import com.usb2uartagent.IUARTConnectorHelper;
import com.usb2uartagent.Usb2UartagentManager;

/**
 * Copyright (c) 2017, SuZhou CsjBot. All Rights Reserved.
 * www.csjbot.com
 * <p>
 * Created by 浦耀宗 at 2017/02/09 0009-14:06.
 * Email: puyz@csjbot.com
 */
public class Usb2UartUpControlHelper implements IUARTConnectorHelper, Usb2UartagentManager.DataHandler {
    private static final byte MSG_HEAD = (byte) 0xAA;
    private static final byte MSG_SRC_TAG = (byte) 0x21;
    private static final int MSG_DATA_LEN_INDEX = 4;
    private static final String TAG = "Usb2UartUpControlHelper";

    private byte[] recvBuf = new byte[5];
    private int recvLenth = 0;
    private int msgLenth = 0;
    private int msgRecvLenth = 0;
    private byte[] msgBuf;

    private static boolean bHandleMsgOk;

    @Override
    public void onDataRecevie(byte[] data) {
        bHandleMsgOk = true;
        ClientManager.getInstance().onReceive(data);
    }

    @Override
    public int init(Context context, String device, int speed) {
        return Usb2UartagentManager.getInstance().init(Usb2UartagentManager.UP_CONTROL_TYPE, speed);
//        return Usb2UartagentManager.getInstance().detectUartIndex(Usb2UartagentManager.UP_CONTROL_TYPE, this, speed);
    }

    @Override
    public int send(byte[] data) {
        return Usb2UartagentManager.getInstance().sendData(Usb2UartagentManager.UP_CONTROL_TYPE, data);
    }

    @Override
    public void destroy() {
        Usb2UartagentManager.getInstance().releaseByType(Usb2UartagentManager.UP_CONTROL_TYPE);
    }

    @Override
    public void setDataReceive(DataReceive receive) {

    }

    @Override
    public void handleData(byte[] data, int length) {
        if (data == null) {
            Csjlogger.error("up control handleData is null !");
            return;
        }

        if (msgBuf == null && (length + recvLenth >= 2)) {
            if (recvLenth == 0) {
                if (data[0] != MSG_HEAD || data[1] != MSG_SRC_TAG) {
                    Csjlogger.debug("up conteol recv data not SYNC HEAD, drop");
                    return;
                }
            } else if (recvLenth == 1) {
                if (recvBuf[0] != MSG_HEAD || data[0] != MSG_SRC_TAG) {
                    Csjlogger.debug("up conteol recv data not SYNC HEAD, drop");
                    recvLenth = 0;
                    return;
                }
            }
        }

        int copyLen;
        if (msgBuf != null) {
            copyLen = msgLenth - msgRecvLenth > length ? length : msgLenth - msgRecvLenth;
            System.arraycopy(data, 0, msgBuf, msgRecvLenth, copyLen);
            msgRecvLenth += copyLen;
            if (msgRecvLenth < msgLenth) {
                return;
            }
        } else {
            copyLen = (recvBuf.length - recvLenth) > length ? length : recvBuf.length - recvLenth;
            System.arraycopy(data, 0, recvBuf, recvLenth, copyLen);
            if (recvLenth + copyLen > MSG_DATA_LEN_INDEX) {
                int dataLength = recvBuf[MSG_DATA_LEN_INDEX] & 0xFF;
                Csjlogger.debug("data length is " + dataLength);
                msgBuf = new byte[recvBuf.length + dataLength + 1];
                msgLenth = msgBuf.length;
                msgRecvLenth = 0;
                System.arraycopy(recvBuf, 0, msgBuf, msgRecvLenth, recvLenth);
                msgRecvLenth += recvLenth;
                recvLenth = 0;
                handleData(data, length);
                return;
            }

            recvLenth += copyLen;
            if (recvLenth < recvBuf.length) {
                return;
            }
        }


        if (msgBuf != null) {
            onDataRecevie(msgBuf);
            msgRecvLenth = 0;
            msgLenth = 0;
            msgBuf = null;
        }

        if (copyLen < length) {
            Csjlogger.debug("multi msg in one stream left :" + (length - copyLen) + " byte");
            byte[] msgTmp = new byte[length - copyLen];
            System.arraycopy(data, copyLen, msgTmp, 0, length - copyLen);
            handleData(msgTmp, length - copyLen);
        }

    }

    public static boolean isbHandleMsgOk() {
        return bHandleMsgOk;
    }
}
